const commonConfig = require('./webpack.common.conf')
const webpackMerge = require('webpack-merge') // used to merge webpack configs
// tools
const chalk = require('chalk')
const path = require('path')
const webpack = require('webpack')
const ip = "127.0.0.1";
// const ip = '192.168.3.9'

// let ip = "192.168.253.3";
// ip = require('ip').address('WLAN');

/**
 * Webpack Plugins
 */
const HtmlWebpackPlugin = require('html-webpack-plugin-for-multihtml')
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

const config = require('./config')
const utils = require('./utils')
const helper = require('./helper')

/**
 * Modify the url that will open on the browser.
 * @param {Array} entry
 */
const postMessageToOpenPage = (entry) => {
    let entrys = Object.keys(entry)
    let openpage = config.dev.openPage
    // exclude vendor entry.
    entrys = entrys.filter(entry => entry !== 'vendor')
    if (entrys.indexOf('main.vue.vue') > -1) {
        openpage += `?page=index.js`
    } else {
        openpage += `?page=${entrys[0]}.js`
    }
    if (entrys.length > 1) {
        openpage += `&entrys=${entrys.join('|')}`
    }
    return openpage
}

const openPage = postMessageToOpenPage(commonConfig[0].entry)

// hotreload server for playground App
const wsServer = require('./hotreload')
let wsTempServer = null

/**
 * Generate multiple entrys
 * @param {Array} entry
 */
const generateHtmlWebpackPlugin = (entry) => {
    let entrys = Object.keys(entry)
    // exclude vendor entry.
    entrys = entrys.filter(entry => entry !== 'vendor')
    const htmlPlugin = entrys.map(name => {
        return new HtmlWebpackPlugin({
            multihtmlCache: true,
            filename: name + '.html',
            template: helper.rootNode(`web/index.html`),
            isDevServer: true,
            chunksSortMode: 'dependency',
            inject: true,
            devScripts: config.dev.htmlOptions.devScripts,
            chunks: ['vendor', name]
        })
    })
    return htmlPlugin
}

/**
 * Webpack configuration for browser.
 */
const devWebpackConfig = webpackMerge(commonConfig[0], {
    /*
     * Options affecting the resolving of modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#module
     */
    module: {
        rules: utils.styleLoaders({sourceMap: config.dev.cssSourceMap, usePostCSS: true})
    },
    /**
     * Developer tool to enhance debugging
     *
     * See: http://webpack.github.io/docs/configuration.html#devtool
     * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
     */
    devtool: config.dev.devtool,
    /*
     * Add additional plugins to the compiler.
     *
     * See: http://webpack.github.io/docs/configuration.html#plugins
     */
    plugins: [
        /**
         * Plugin: webpack.DefinePlugin
         * Description: The DefinePlugin allows you to create global constants which can be configured at compile time.
         *
         * See: https://webpack.js.org/plugins/define-plugin/
         */
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': config.dev.env
            }
        }),
        /*
         * Plugin: HtmlWebpackPlugin
         * Description: Simplifies creation of HTML files to serve your webpack bundles.
         * This is especially useful for webpack bundles that include utils hash in the filename
         * which changes every compilation.
         *
         * See: https://github.com/ampedandwired/html-webpack-plugin
         */
        ...generateHtmlWebpackPlugin(commonConfig[0].entry),
        /*
         * Plugin: ScriptExtHtmlWebpackPlugin
         * Description: Enhances html-webpack-plugin functionality
         * with different deployment options for your scripts including:
         *
         * See: https://github.com/numical/script-ext-html-webpack-plugin
         */
        new ScriptExtHtmlWebpackPlugin({
            defaultAttribute: 'defer'
        })
    ],
    /**
     * Webpack Development Server configuration
     * Description: The webpack-dev-server is utils little node.js Express server.
     * The server emits information about the compilation state to the client,
     * which reacts to those events.
     *
     * See: https://webpack.github.io/docs/webpack-dev-server.html
     */
    devServer: {
        clientLogLevel: 'warning',
        compress: true,
        contentBase: config.dev.contentBase,
        host: config.dev.host,
        port: config.dev.port,
        historyApiFallback: config.dev.historyApiFallback,
        public: config.dev.public,
        open: config.dev.open,
        watchContentBase: config.dev.watchContentBase,
        overlay: config.dev.errorOverlay
            ? {warnings: false, errors: true}
            : false,
        proxy: config.dev.proxyTable,
        quiet: true, // necessary for FriendlyErrorsPlugin
        openPage: encodeURI(openPage),
        watchOptions: config.dev.watchOptions
    }
})

/**
 * Webpack configuration for weex.
 */
const weexConfig = webpackMerge(commonConfig[1], {
    watch: true
})

// build source to weex_bundle with watch mode.
webpack(weexConfig, (err, stats) => {
    if (err) {
        console.err('COMPILE ERROR:', err.stack)
    } else {
        wsTempServer && wsTempServer.sendSocketMessage()
    }
})

module.exports = new Promise((resolve, reject) => {
    portfinder.basePort = process.env.PORT || config.dev.port
    portfinder.getPort((err, port) => {
        if (err) {
            reject(err)
        } else {
            // publish the new Port, necessary for e2e tests
            process.env.PORT = port
            // add port to devServer config
            devWebpackConfig.devServer.port = port
            devWebpackConfig.devServer.public = `${ip}:${port}`
            devWebpackConfig.devServer.openPage += `&wsport=${port + 1}`
            // Add FriendlyErrorsPlugin
            devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
                compilationSuccessInfo: {
                    messages: [
                        `Your application is running here: ${chalk.yellow(`http://${devWebpackConfig.devServer.host}:${port}`)}.`
                    ],
                },
                onErrors: config.dev.notifyOnErrors
                    ? utils.createNotifierCallback()
                    : undefined
            }))
            wsTempServer = new wsServer(port + 1)
            resolve(devWebpackConfig)
        }
    })
})
